Skip to content

release: 0.35.1#88

Open
stainless-app[bot] wants to merge 40 commits intomainfrom
release-please--branches--main--changes--next--components--hyperspell
Open

release: 0.35.1#88
stainless-app[bot] wants to merge 40 commits intomainfrom
release-please--branches--main--changes--next--components--hyperspell

Conversation

@stainless-app
Copy link
Copy Markdown
Contributor

@stainless-app stainless-app bot commented Mar 20, 2026

Automated Release PR

0.35.1 (2026-04-09)

Full Changelog: v0.35.0...v0.35.1

Features

Bug Fixes

  • internal: gitignore generated oidc dir (a305f3d)

Chores

  • ci: escape input path in publish-npm workflow (40c8402)
  • ci: skip lint on metadata-only changes (14012e7)
  • configure new SDK language (2b1db35)
  • internal: codegen related update (74743e3)
  • internal: fix MCP server import ordering (aa4d800)
  • internal: fix MCP server TS errors that occur with required client options (b7abcfb)
  • internal: improve local docs search for MCP servers (eee2438)
  • internal: improve local docs search for MCP servers (f218072)
  • internal: support custom-instructions-path flag in MCP servers (c6d4043)
  • internal: support local docs search in MCP servers (4a9b2cf)
  • internal: support type annotations when running MCP in local execution mode (41a4e6a)
  • internal: update gitignore (9270ff5)
  • internal: update multipart form array serialization (97f213b)
  • mcp-server: add support for session id, forward client info (9e3018f)
  • mcp-server: increase local docs search result count from 5 to 10 (65850d9)
  • mcp-server: log client info (5f1ad6d)
  • tests: bump steady to v0.19.4 (e614b67)
  • tests: bump steady to v0.19.5 (eadfc98)
  • tests: bump steady to v0.19.6 (4ed8bba)
  • tests: bump steady to v0.19.7 (6aaa435)
  • tests: bump steady to v0.20.1 (bb96b8b)
  • tests: bump steady to v0.20.2 (2a71a6e)
  • update SDK settings (4ee9dca)
  • update SDK settings (752879e)

Refactors

  • tests: switch from prism to steady (75ac934)

This pull request is managed by Stainless's GitHub App.

The semver version number is based on included commit messages. Alternatively, you can manually set the version number in the title of this pull request.

For a better experience, it is recommended to use either rebase-merge or squash-merge when merging this pull request.

🔗 Stainless website
📚 Read the docs
🙋 Reach out for help or questions

@stainless-app
Copy link
Copy Markdown
Contributor Author

stainless-app bot commented Mar 20, 2026

🧪 Testing

To try out this version of the SDK:

npm install 'https://pkg.stainless.com/s/hyperspell-typescript/74743e38189fcce572490e5ad3d0700209836db5/dist.tar.gz'

Expires at: Sat, 09 May 2026 10:51:36 GMT
Updated at: Thu, 09 Apr 2026 10:51:36 GMT

@canaries-inc
Copy link
Copy Markdown

canaries-inc bot commented Mar 20, 2026

Canary encountered an internal error while analyzing this PR.

@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next--components--hyperspell branch from 6972295 to d19a5b9 Compare March 21, 2026 05:08
@entelligence-ai-pr-reviews
Copy link
Copy Markdown



Confidence Score: 5/5 - Safe to Merge

  • No new review comments were generated, indicating the PR appears clean to the automated review.
  • No critical, significant, or high-risk issues were identified in the heuristic analysis.
  • 8 out of 11 changed files were reviewed with zero issues flagged across all severity levels.
  • No existing unresolved comments remain, suggesting previous concerns have been addressed.

@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next--components--hyperspell branch from d19a5b9 to 76a7033 Compare March 21, 2026 05:14
@entelligence-ai-pr-reviews
Copy link
Copy Markdown



Confidence Score: 5/5 - Safe to Merge

  • No new review comments were generated, indicating the PR appears clean from an automated review perspective.
  • No critical, significant, or high-risk issues were identified in the heuristic analysis.
  • 8 out of 11 changed files were reviewed with no issues found, providing reasonable coverage confidence.
  • No existing unresolved comments that could indicate lingering concerns.

@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next--components--hyperspell branch from 76a7033 to abd5f3a Compare March 21, 2026 21:30
@entelligence-ai-pr-reviews
Copy link
Copy Markdown



Confidence Score: 5/5 - Safe to Merge

  • No new review comments were generated, indicating the PR appears clean from an automated review perspective.
  • No critical, significant, or high-risk issues were identified in the heuristic analysis.
  • 15 out of 18 changed files were reviewed, providing good coverage with no issues found.
  • No existing unresolved comments that would block merging.

@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next--components--hyperspell branch from abd5f3a to 651d17f Compare March 22, 2026 08:09
@entelligence-ai-pr-reviews
Copy link
Copy Markdown



Confidence Score: 5/5 - Safe to Merge

  • No critical or significant issues found
  • 15/18 changed files reviewed (83% coverage)

@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next--components--hyperspell branch from 651d17f to fc292db Compare March 23, 2026 08:03
@entelligence-ai-pr-reviews
Copy link
Copy Markdown



Confidence Score: 5/5 - Safe to Merge

  • No critical or significant issues found
  • 15/18 changed files reviewed (83% coverage)

@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next--components--hyperspell branch from fc292db to 08cc52a Compare March 23, 2026 22:30
@entelligence-ai-pr-reviews
Copy link
Copy Markdown



Confidence Score: 5/5 - Safe to Merge

  • No new review comments were generated, indicating the PR is clean from an automated review perspective.
  • No critical, significant, or high-risk issues were identified in the heuristic analysis.
  • 15 out of 18 changed files were reviewed with zero issues flagged, providing good coverage confidence.
  • No existing unresolved comments carry over from previous reviews that would block merging.

@stainless-app
Copy link
Copy Markdown
Contributor Author

stainless-app bot commented Mar 24, 2026

Release version edited manually

The Pull Request version has been manually set to 0.35.1 and will be used for the release.

If you instead want to use the version number 0.36.0 generated from conventional commits, just remove the label autorelease: custom version from this Pull Request.

@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next--components--hyperspell branch from 08cc52a to 15abf4d Compare March 24, 2026 05:10
@entelligence-ai-pr-reviews
Copy link
Copy Markdown



Confidence Score: 5/5 - Safe to Merge

  • No critical or significant issues found
  • 15/19 changed files reviewed (79% coverage)

@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next--components--hyperspell branch from 15abf4d to 2dbef30 Compare March 24, 2026 05:14
@entelligence-ai-pr-reviews
Copy link
Copy Markdown



Confidence Score: 5/5 - Safe to Merge

  • No critical or significant issues found
  • 16/20 changed files reviewed (80% coverage)

@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next--components--hyperspell branch from 2dbef30 to b86942f Compare March 24, 2026 05:16
@entelligence-ai-pr-reviews
Copy link
Copy Markdown



Confidence Score: 5/5 - Safe to Merge

  • No critical or significant issues found
  • 16/20 changed files reviewed (80% coverage)

@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next--components--hyperspell branch from b86942f to dd246c5 Compare March 24, 2026 17:30
@entelligence-ai-pr-reviews
Copy link
Copy Markdown



Confidence Score: 5/5 - Safe to Merge

  • No critical or significant issues found
  • 16/20 changed files reviewed (80% coverage)

@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next--components--hyperspell branch 2 times, most recently from 0b83ccb to d4e4451 Compare March 25, 2026 03:29
@entelligence-ai-pr-reviews
Copy link
Copy Markdown



Confidence Score: 5/5 - Safe to Merge

  • No new review comments were generated, indicating the PR is clean with no identified issues.
  • No existing unresolved comments to consider, meaning there are no lingering concerns from previous reviews.
  • 16 out of 21 changed files were reviewed with no issues found, providing good coverage confidence.
  • Heuristic analysis shows zero critical, significant, high-risk, or medium issues detected.

@entelligence-ai-pr-reviews
Copy link
Copy Markdown



Confidence Score: 5/5 - Safe to Merge

  • No new review comments were generated, indicating the PR appears clean from an automated review perspective.
  • No critical, significant, or high-risk issues were identified in the heuristic analysis.
  • Coverage of 16/21 changed files is reasonable, and no unresolved existing comments are blocking the merge.
  • The absence of any flagged issues across all severity levels supports a safe-to-merge assessment.

@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next--components--hyperspell branch from d4e4451 to a7b2b11 Compare March 26, 2026 17:30
@entelligence-ai-pr-reviews
Copy link
Copy Markdown


Confidence Score: 1/5 - Blocking Issues

Not safe to merge — code-tool-worker.ts executes user-supplied code from the request body directly via eval/dynamic execution with no sandboxing, representing a critical remote code execution vulnerability that gives any caller full access to the process environment and credentials. Compounding this, the globalThis.console mutation in the same file creates a confirmed race condition under concurrent requests where log lines and error lines will bleed across requests, a bug flagged repeatedly in at least eight prior unresolved review comments that have gone unaddressed. The PR does deliver meaningful value — expanding gmail_actions support across multiple type files and introducing LocalDocsSearch for offline MCP documentation — but the security and correctness issues in code-tool-worker.ts, plus the static import fs from 'fs/promises' in instructions.ts that will crash module initialization in Deno/edge runtimes, make this unsafe to ship.

Key Findings:

  • Arbitrary code execution risk in code-tool-worker.ts: the code parameter from req.json() is executed without sandboxing, allowing any caller to run arbitrary code with full access to the worker process, environment variables, and network — a critical security vulnerability.
  • Race condition in globalThis.console mutation (lines 270-278 of code-tool-worker.ts): concurrent async requests will overwrite each other's console interceptor, causing log_lines/err_lines to capture output from the wrong request; this exact bug has been raised in at least 8 previous unresolved review comments and remains unfixed.
  • Static top-level import fs from 'fs/promises' in instructions.ts will cause module initialization failure in non-Node.js runtimes (Deno, Cloudflare Workers), silently breaking those environments at startup — inconsistent with the deliberate dynamic await import('node:fs') pattern already used in code-tool.ts.
  • McpOptions object returned in options.ts (lines 179-185) is missing several properties (stainlessApiKey, codeAllowHttpGets, codeAllowedMethods, etc.) defined in the McpOptions type, a pre-existing unresolved correctness issue that could cause silent misconfiguration.
Files requiring special attention
  • packages/mcp-server/src/code-tool-worker.ts
  • packages/mcp-server/src/instructions.ts
  • packages/mcp-server/src/options.ts

@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next--components--hyperspell branch from f29ed6a to fce5750 Compare April 3, 2026 21:30
Comment on lines 8 to +10
import { Hyperspell, ClientOptions } from 'hyperspell';

async function tseval(code: string) {
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctness: The code argument passed to tseval originates directly from the request body (req.json()) with no sandboxing beyond the proxy — a malicious caller can execute arbitrary code in the worker process by crafting the code field of the request payload.

🤖 AI Agent Prompt for Cursor/Windsurf

📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue

In packages/mcp-server/src/code-tool-worker.ts at lines 8-10, the tseval function dynamically imports and executes arbitrary TypeScript code that comes directly from an untrusted HTTP request body. Ensure this worker runs in a fully isolated sandbox (e.g., a separate Deno/Worker process with no access to secrets or the filesystem), enforce strict origin/auth checks before the fetch handler is invoked, or document the trust boundary explicitly if the endpoint is internal-only.

Comment on lines 271 to 278
const log_lines: string[] = [];
const err_lines: string[] = [];
const console = {
const originalConsole = globalThis.console;
globalThis.console = {
...originalConsole,
log: (...args: unknown[]) => {
log_lines.push(util.format(...args));
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctness: 🐛 Mutating globalThis.console is not safe under concurrent requests — if two requests are in-flight simultaneously, Request B will overwrite globalThis.console with its own capture object, so Request A's console.log calls will be recorded into B's log_lines, and the finally restores will race each other. The previous local const console shadowing was request-scoped; this new approach makes console capture a shared mutable global that breaks under concurrency.

🤖 AI Agent Prompt for Cursor/Windsurf

📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue

In packages/mcp-server/src/code-tool-worker.ts, lines 271-278, the diff replaces a local `const console = {...}` with a mutation of `globalThis.console`. This creates a race condition when multiple requests are handled concurrently: whichever request last sets `globalThis.console` wins, causing cross-request log capture pollution and lost logs. Fix this by using an AsyncLocalStorage or similar per-request context to pass the capture console to the evaluated code, rather than mutating the shared global. Alternatively, if evaluated code must use globalThis.console, serialize request handling or find another isolation mechanism.


export interface MemoryUploadParams {
/**
* The file to ingest.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctness: Changing file from Uploadable to string breaks callers passing File, Blob, Buffer, or ReadableStream objects, which are the expected input types for a multipart file upload using multipartFormRequestOptions. A plain string value passed to multipartFormRequestOptions will be sent as-is (e.g. a filename string), not as actual binary file content, silently producing malformed uploads.

🤖 AI Agent Prompt for Cursor/Windsurf

📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue

In `src/resources/memories.ts`, line 844, the `file` field in `MemoryUploadParams` was changed from `Uploadable` to `string`. This breaks the ability to pass actual file objects (File, Blob, Buffer, ReadableStream) to the upload method, which relies on `multipartFormRequestOptions` for multipart form data. Revert this field back to `Uploadable` to preserve correct upload behavior and maintain API compatibility.

@entelligence-ai-pr-reviews
Copy link
Copy Markdown


Confidence Score: 1/5 - Blocking Issues

Not safe to merge — this PR introduces critical security and correctness issues that must be resolved before merging. The code-tool-worker.ts file executes user-supplied code from req.json() without any sandboxing, allowing arbitrary code execution by any caller who can reach the endpoint; this is a severe remote code execution vulnerability. Additionally, globalThis.console mutation in the same file creates a well-documented race condition under concurrent requests where log lines will bleed between requests and finally restores will corrupt state, and this issue has been flagged in no fewer than eight previous unresolved review comments with zero remediation. The memories.ts change narrowing file from Uploadable to string is a breaking API regression that will silently corrupt multipart uploads for callers passing File, Blob, Buffer, or ReadableStream objects.

Key Findings:

  • In code-tool-worker.ts, the code field from req.json() is passed directly to tseval with no input validation, sandboxing, or allowlisting — an attacker with network access to this worker endpoint can execute arbitrary code in the worker process, constituting a critical RCE vulnerability.
  • The globalThis.console mutation pattern in code-tool-worker.ts (lines 270-278) is fundamentally unsafe for async concurrent handlers: two overlapping requests will cross-contaminate each other's log_lines arrays and the finally block's restore will set console to the wrong captured object — this has been flagged in 8 separate previous review comments and remains entirely unaddressed.
  • The file parameter type change in src/resources/memories.ts from Uploadable (which includes File, Blob, Buffer, ReadableStream) to string is a breaking change that will cause multipart form uploads to be sent as raw string bodies, silently producing malformed requests rather than failing loudly.
  • A pre-existing and still-open concern in packages/mcp-server/src/instructions.ts uses a static top-level import fs from 'fs/promises' which will crash module initialization in Deno or Cloudflare Workers environments, and packages/mcp-server/src/options.ts returns an McpOptions object missing several required properties (stainlessApiKey, codeAllowHttpGets, codeAllowedMethods), both of which remain unresolved from prior reviews.
Files requiring special attention
  • packages/mcp-server/src/code-tool-worker.ts
  • src/resources/memories.ts
  • packages/mcp-server/src/instructions.ts
  • packages/mcp-server/src/options.ts

@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next--components--hyperspell branch from fce5750 to 7d81670 Compare April 7, 2026 08:11
import { Hyperspell, ClientOptions } from 'hyperspell';

async function tseval(code: string) {
return import('data:application/typescript;charset=utf-8;base64,' + Buffer.from(code).toString('base64'));
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctness: Buffer is a Node.js global not available in Deno or edge runtimes; the parseError function explicitly mentions Deno and the module uses export default { fetch } (edge worker pattern), so this will throw ReferenceError: Buffer is not defined at runtime in those environments.

🤖 AI Agent Prompt for Cursor/Windsurf

📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue

In packages/mcp-server/src/code-tool-worker.ts at line 11, the `tseval` function uses `Buffer.from(code).toString('base64')` to base64-encode the TypeScript code. `Buffer` is a Node.js-only global and is not available in Deno or edge runtimes (the file uses `export default { fetch }` pattern and `parseError` mentions Deno explicitly). Replace `Buffer.from(code).toString('base64')` with a runtime-agnostic base64 encoding such as `btoa(unescape(encodeURIComponent(code)))` to handle Unicode safely across all environments.


export interface MemoryUploadParams {
/**
* The file to ingest.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctness: Changing file from Uploadable to string is a breaking change — callers passing File, Blob, Buffer, or ReadableStream objects will now get TypeScript type errors. The upload method still calls multipartFormRequestOptions, which is designed for actual binary file uploads, so restricting to string may silently break real file upload use cases at runtime.

🤖 AI Agent Prompt for Cursor/Windsurf

📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue

In file `src/resources/memories.ts`, line 844, the type of `file` in `MemoryUploadParams` was changed from `Uploadable` to `string`. This is a breaking change for any caller passing `File`, `Blob`, `Buffer`, or `ReadableStream` objects, and may silently break binary file uploads since the `upload` method still uses `multipartFormRequestOptions`. If the intent is to support both file paths (strings) and actual file objects, restore the type to `Uploadable` (or use a union like `Uploadable | string`). If only string file paths are now supported, verify that `multipartFormRequestOptions` handles plain strings correctly and update the method documentation accordingly.

Comment on lines 271 to 272
const log_lines: string[] = [];
const err_lines: string[] = [];
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctness: 🔴 Mutating globalThis.console is not concurrency-safe in a server handling multiple simultaneous requests — request B will capture request A's patched console as its originalConsole, and log lines from different requests will bleed into each other's log_lines/err_lines arrays until the finally block restores the wrong reference.

🤖 AI Agent Prompt for Cursor/Windsurf

📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue

In packages/mcp-server/src/code-tool-worker.ts, lines 271-278, the diff replaces a local `const console` shadow with direct mutation of `globalThis.console`. This is unsafe under concurrent requests: each request saves and restores `globalThis.console`, but overlapping requests can interleave such that (1) one request's `log` override overwrites another's, and (2) the 'original' captured by request B is already request A's patched console. Fix by keeping the original approach of passing a custom console-like object directly to user code (e.g., inject it as a parameter or use a module-scoped override only inside `tseval`) instead of mutating the shared global.

@entelligence-ai-pr-reviews
Copy link
Copy Markdown


Confidence Score: 1/5 - Blocking Issues

Not safe to merge — this PR has multiple critical, unresolved correctness bugs that have been flagged repeatedly across prior reviews without being addressed. In code-tool-worker.ts, the use of Buffer as a global will throw ReferenceError: Buffer is not defined in Deno environments (the intended runtime), and the mutation of globalThis.console creates a well-documented race condition where concurrent requests will bleed log lines into each other's log_lines/err_lines arrays. Additionally, the type change of file from Uploadable to string in src/resources/memories.ts is a breaking API change that will silently break callers passing File, Blob, or Buffer objects despite the underlying multipartFormRequestOptions call still expecting binary data. While the PR's goals — MCP local search, session tracking, and Gmail Actions support — are valuable, the core runtime and API correctness issues make this unsafe to ship.

Key Findings:

  • Buffer.from(code) in code-tool-worker.ts is used as a Node.js global in what is clearly a Deno/edge runtime context (evidenced by export default { fetch }, node: import prefixes, and Deno-specific stack trace parsing in parseError); this will throw a ReferenceError at runtime and has been flagged in at least 5 separate prior review comments without resolution.
  • The globalThis.console mutation pattern in code-tool-worker.ts (lines 270-278) is not concurrency-safe: two overlapping async requests will overwrite each other's console interceptor, causing log output to be attributed to the wrong request — this has been flagged in at least 6 prior review comments and remains unaddressed.
  • Changing memories.ts upload's file parameter from Uploadable to string is a breaking type change — existing callers passing File, Blob, Buffer, or ReadableStream will get TypeScript errors, and the method still calls multipartFormRequestOptions which is designed for actual binary uploads, creating a semantic mismatch.
  • In packages/mcp-server/src/instructions.ts, a static top-level import fs from 'fs/promises' will cause module initialization failure in non-Node.js runtimes at load time (not just at call time), and in packages/mcp-server/src/options.ts the returned McpOptions object is missing properties like stainlessApiKey, codeAllowHttpGets, and codeAllowedMethods that are defined in the type — both pre-existing issues that remain open.
Files requiring special attention
  • packages/mcp-server/src/code-tool-worker.ts
  • src/resources/memories.ts
  • packages/mcp-server/src/instructions.ts
  • packages/mcp-server/src/options.ts

@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next--components--hyperspell branch from 7d81670 to 2b4d27c Compare April 8, 2026 03:31
Comment on lines 271 to 272
const log_lines: string[] = [];
const err_lines: string[] = [];
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctness: 🐛 Mutating globalThis.console is not safe under concurrent requests. If two requests overlap, Request B captures Request A's overriding console as its originalConsole, and when B's finally block restores it, A's capturing function becomes the permanent global console — leaking captured log lines across requests indefinitely.

🤖 AI Agent Prompt for Cursor/Windsurf

📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue

In packages/mcp-server/src/code-tool-worker.ts, lines 271-272 introduce a race condition: `globalThis.console` is mutated for the duration of an async request, but concurrent requests can interleave their save/restore operations, causing one request's capturing console to leak as the global after another request's `finally` block runs. Fix this by avoiding mutation of the shared global — instead, pass a custom console object directly into the evaluated code's scope (e.g. inject it as a variable alongside `client`), or use a per-invocation wrapper that does not mutate `globalThis`.

@entelligence-ai-pr-reviews
Copy link
Copy Markdown


Confidence Score: 1/5 - Blocking Issues

Not safe to merge — this PR introduces multiple critical correctness issues that remain unresolved across 18 prior review comments and are confirmed again in the current review. Specifically, the mutation of globalThis.console in code-tool-worker.ts creates a well-documented race condition under concurrent requests where one request's finally block can permanently install another request's capturing function as the global console, leaking log lines across requests. Additionally, local-docs-search.ts will throw an unhandled "query is empty" exception from MiniSearch.search('') when an empty string is passed, with no guard in place. While the PR meaningfully expands the Gmail Actions integration and adds the effort parameter to MemorySearchParams, these runtime-crashing bugs and the unresolved security concern about unsandboxed code execution via tseval in code-tool-worker.ts make this unsafe to ship.

Key Findings:

  • The globalThis.console mutation pattern in code-tool-worker.ts (lines 270-278) is a confirmed race condition: concurrent async requests will interleave such that Request B captures Request A's patched console as originalConsole, and when B's finally block restores it, A's interceptor becomes the permanent global — this bug has appeared in 12 separate unresolved review comments and is flagged again at score 8.5 in the current review.
  • In local-docs-search.ts, this.methodIndex.search(query) and this.proseIndex.search(query) are called without any empty-string guard; MiniSearch throws a runtime "query is empty" error for this input, meaning any caller that passes an empty query string will receive an unhandled exception rather than an empty result set.
  • The code-tool-worker.ts file uses Buffer as a global (e.g., Buffer.from(code)), but multiple unresolved comments note that Buffer is not available as a global in Deno environments (evidenced by the export default { fetch } edge-worker pattern and Deno-specific stack trace parsing), meaning this will throw ReferenceError: Buffer is not defined at runtime in the intended deployment environment.
  • The options.ts McpOptions return object is missing several properties from defaultOptions (stainlessApiKey, codeAllowHttpGets, codeAllowedMethods, etc.), and instructions.ts uses a static top-level import fs from 'fs/promises' that will cause module initialization failure in non-Node runtimes — both flagged as unresolved correctness issues in prior reviews.
Files requiring special attention
  • packages/mcp-server/src/code-tool-worker.ts
  • packages/mcp-server/src/local-docs-search.ts
  • packages/mcp-server/src/instructions.ts
  • packages/mcp-server/src/options.ts

@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next--components--hyperspell branch from 2b4d27c to dfc0fe2 Compare April 8, 2026 22:30
Comment on lines 271 to 278
const log_lines: string[] = [];
const err_lines: string[] = [];
const console = {
const originalConsole = globalThis.console;
globalThis.console = {
...originalConsole,
log: (...args: unknown[]) => {
log_lines.push(util.format(...args));
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctness: Mutating globalThis.console is not safe under concurrent requests: if two requests interleave across the await tseval(...) / await run_(...) calls, one request's console override will clobber the other's, causing log lines to be captured into the wrong request's arrays or lost entirely after the finally restores.

🤖 AI Agent Prompt for Cursor/Windsurf

📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue

In packages/mcp-server/src/code-tool-worker.ts around lines 271-278, the code mutates globalThis.console to capture log output from dynamically evaluated user code. Because the fetch handler is async and yields at `await tseval(...)` and `await run_(...)`, concurrent requests can interleave and overwrite each other's globalThis.console override, causing log lines to be routed to the wrong request's log_lines/err_lines arrays or discarded. Consider passing a scoped console object directly into the evaluated code (e.g., injecting it as a global in the data URL or using a per-request wrapper) instead of mutating the shared globalThis.console.

@entelligence-ai-pr-reviews
Copy link
Copy Markdown


Confidence Score: 2/5 - Changes Needed

Not safe to merge — packages/mcp-server/src/code-tool-worker.ts contains a well-documented and repeatedly flagged concurrency bug where globalThis.console is mutated directly in the async fetch handler, meaning overlapping requests will corrupt each other's captured log streams and leave the global console in an undefined state after the finally block runs. Beyond the concurrency hazard, multiple unresolved reviews flag that user-supplied code from req.json() is executed via tseval without sandboxing (arbitrary code execution risk), Buffer is used as a global in what appears to be a Deno runtime context where it isn't available, and instructions.ts uses a static import fs from 'fs/promises' that will crash module initialization in non-Node runtimes. The PR delivers real value in the mock-server migration, local-docs-search, and Gmail Actions support, but the recurring unresolved correctness issues in the MCP server worker — particularly the security concern around unsandboxed code execution and the concurrency race on globalThis.console — make this unsafe to merge in its current state.

Key Findings:

  • In code-tool-worker.ts, globalThis.console is replaced inside each async fetch handler with no mutex or AsyncLocalStorage isolation; concurrent requests will race to overwrite each other's interceptor, routing log lines to the wrong request's arrays and leaving globalThis.console pointing to a partially-restored object after the finally block runs.
  • User-controlled code from req.json() is passed directly to tseval() with no sandboxing beyond a proxy; an attacker who can reach this endpoint gains arbitrary code execution in the server process — a critical security concern flagged repeatedly in prior reviews that remains unaddressed.
  • Buffer.from(code) is called as a global in code-tool-worker.ts, but the file's export default { fetch } pattern and Deno-specific stack-trace parsing strongly indicate a Deno runtime, where Buffer is not globally available, meaning this will throw ReferenceError at runtime.
  • In instructions.ts, the static top-level import fs from 'fs/promises' will cause the module to fail to initialize in Deno or edge runtimes at load time, not merely at call time — a regression risk given the MCP server's stated multi-runtime target.
Files requiring special attention
  • packages/mcp-server/src/code-tool-worker.ts
  • packages/mcp-server/src/instructions.ts
  • packages/mcp-server/src/options.ts

@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next--components--hyperspell branch from dfc0fe2 to 532797f Compare April 9, 2026 02:30
Comment on lines 271 to 272
const log_lines: string[] = [];
const err_lines: string[] = [];
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctness: 🐛 Mutating globalThis.console inside an async function creates a race condition: if two requests are in-flight concurrently, the second request overwrites the first's patched console, causing the first request's finally block to restore the wrong original and the second's log capture to be silently dropped or mixed.

🤖 AI Agent Prompt for Cursor/Windsurf

📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue

In `packages/mcp-server/src/code-tool-worker.ts`, lines 271-272 (and the matching `finally` block), `globalThis.console` is overwritten inside an async `fetch` handler. Because multiple requests can be in-flight concurrently (each `await` is a yield point), a second request will overwrite the first's patched console before the first's `finally` restores it, causing mixed log capture and incorrect restoration. Fix this by avoiding mutation of the shared global: instead of patching `globalThis.console`, pass a local console-like object directly into the evaluated code, or serialize requests so only one patch is active at a time.

@entelligence-ai-pr-reviews
Copy link
Copy Markdown


Confidence Score: 1/5 - Blocking Issues

Not safe to merge — the code-tool-worker.ts file has a critical, unresolved race condition where globalThis.console is mutated in an async fetch handler, meaning concurrent requests will corrupt each other's log capture and finally blocks will restore the wrong original console, silently losing output or mixing logs between requests. Beyond this correctness bug, a persistent security concern about executing unsanitized user-supplied code directly via tseval without sandboxing represents an arbitrary code execution vector for any caller that can reach the endpoint. Additionally, Buffer is used as a global in what appears to be a Deno runtime context (evidenced by export default { fetch } pattern and Deno-specific stack trace parsing), which will throw ReferenceError: Buffer is not defined at runtime. While the PR's additions — Gmail Actions support, effort parameter for MemorySearchParams, LocalDocsSearch via MiniSearch, and Prism-to-Steady mock server migration — are valuable, the unresolved critical issues in code-tool-worker.ts and instructions.ts block safe merging.

Key Findings:

  • The globalThis.console mutation pattern in code-tool-worker.ts (lines 270-278) is fundamentally unsafe for concurrent async requests: Request B overwrites the patched console before Request A's finally restores it, causing Request A to restore Request B's interceptor and leaving the global console in an inconsistent state — this has been flagged in at least 10 prior unresolved review comments and remains unfixed.
  • The tseval invocation in code-tool-worker.ts executes user-supplied code from req.json() with no sandboxing beyond a proxy, constituting an arbitrary code execution vulnerability — any authenticated caller can run arbitrary server-side code, flagged multiple times in prior reviews with no resolution.
  • Buffer.from(code) is used as a bare global in code-tool-worker.ts, but the runtime is Deno (indicated by export default { fetch } pattern and Deno-specific V8 stack parsing), where Buffer is not available globally without explicit Node.js compat mode, causing a ReferenceError at runtime.
  • In instructions.ts, a static top-level import fs from 'fs/promises' will cause module initialization failure in non-Node.js runtimes at load time (not just when the code path is exercised), and options.ts returns an McpOptions object missing several required properties (stainlessApiKey, codeAllowHttpGets, codeAllowedMethods) that are defined in the type, risking undefined access errors downstream.
Files requiring special attention
  • packages/mcp-server/src/code-tool-worker.ts
  • packages/mcp-server/src/instructions.ts
  • packages/mcp-server/src/options.ts

@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next--components--hyperspell branch from 532797f to 0e9af24 Compare April 9, 2026 10:48
@stainless-app stainless-app bot force-pushed the release-please--branches--main--changes--next--components--hyperspell branch from 0e9af24 to dc0dced Compare April 9, 2026 10:51
Comment on lines 271 to 278
const log_lines: string[] = [];
const err_lines: string[] = [];
const console = {
const originalConsole = globalThis.console;
globalThis.console = {
...originalConsole,
log: (...args: unknown[]) => {
log_lines.push(util.format(...args));
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Correctness: 🔴 Mutating globalThis.console is shared mutable state — if two requests execute concurrently, one request's finally block will restore the original console while the other request is still running, causing its log/error output to escape capture (or be lost entirely) and potentially mixing log lines across requests.

🤖 AI Agent Prompt for Cursor/Windsurf

📋 Copy this prompt to your AI coding assistant (Cursor, Windsurf, etc.) to get help fixing this issue

In packages/mcp-server/src/code-tool-worker.ts, lines 271-278, the code mutates `globalThis.console` to intercept log/error calls during user code execution. This creates a race condition in concurrent request handling: if two requests overlap, one request's `finally` block restoring `globalThis.console = originalConsole` will clobber the other request's override mid-execution. Fix this by not mutating `globalThis.console` at all — instead, pass a custom console object directly into the evaluated code's scope, or use a mechanism that doesn't rely on global mutable state. For example, pass the overridden console as a variable that the evaluated code can close over, rather than replacing the global.

@entelligence-ai-pr-reviews
Copy link
Copy Markdown


Confidence Score: 1/5 - Blocking Issues

Not safe to merge — this PR introduces a critical race condition in packages/mcp-server/src/code-tool-worker.ts where globalThis.console is mutated inside an async fetch handler, meaning two concurrent requests will corrupt each other's console capture (Request B overwrites A's patched console, and A's finally block restores B's override, causing log loss or cross-request mixing). Additionally, Buffer.from(code) in the same file uses a Node.js global that is not natively available in Deno environments (evidenced by the Deno-specific stack parsing and export default { fetch } pattern), which will throw a ReferenceError at runtime. The PR does deliver value — Gmail Actions union type additions, the effort parameter for MemorySearchParams, and MCP server enhancements — but these critical unresolved correctness issues in the worker file, compounded by a static import fs from 'fs/promises' in instructions.ts that will crash module initialization in non-Node runtimes, block safe merging.

Key Findings:

  • In code-tool-worker.ts, mutating globalThis.console inside an async request handler is not concurrency-safe: concurrent requests will overwrite each other's console interceptor mid-execution, causing log_ and error_ capture arrays to receive interleaved or missing output, and finally blocks may restore the wrong original console — this is a functional correctness bug under any real server load.
  • In code-tool-worker.ts, Buffer.from(code) references the Node.js Buffer global which does not exist in Deno environments without explicit compatibility mode — the file's use of export default { fetch }, node:path/node:util imports, and Deno-specific stack trace parsing all indicate a Deno runtime target, making this a ReferenceError crash at runtime.
  • In instructions.ts, the static top-level import fs from 'fs/promises' will cause module initialization failure in non-Node.js runtimes (Deno, Cloudflare Workers, edge environments) even when the file-reading code path is never reached — unlike the dynamic import pattern used elsewhere in the codebase.
  • The code parameter passed to tseval in code-tool-worker.ts originates directly from the unauthenticated request body with no sandboxing, representing an arbitrary code execution vulnerability if this endpoint is reachable by untrusted callers — a security concern that remains unaddressed across multiple review cycles.
Files requiring special attention
  • packages/mcp-server/src/code-tool-worker.ts
  • packages/mcp-server/src/instructions.ts

@entelligence-ai-pr-reviews
Copy link
Copy Markdown


Confidence Score: 1/5 - Blocking Issues

Not safe to merge — packages/mcp-server/src/code-tool-worker.ts contains multiple critical, unresolved correctness and security issues that make this PR blocking. The globalThis.console mutation inside the async fetch handler is a confirmed race condition: concurrent requests will corrupt each other's log routing, and the new review comment confirms that prototype-bound methods like console.warn and console.info won't survive the spread-copy, causing TypeError at runtime. Beyond the concurrency bug, unsandboxed execution of user-supplied code via tseval represents an arbitrary code execution vulnerability, and Buffer usage in what appears to be a Deno runtime will throw ReferenceError on any invocation. While the PR delivers legitimate value (Gmail Actions support, mock server migration from Prism to Steady, new API resource types), the MCP server worker has foundational safety and correctness problems that must be resolved before shipping.

Key Findings:

  • In code-tool-worker.ts, spreading {...originalConsole} to capture the console object misses all prototype-inherited methods (warn, info, debug, trace), so any user code or internal call to console.warn() will throw TypeError: console.warn is not a function at runtime — a confirmed high-severity bug introduced or left unresolved in this PR.
  • Mutating globalThis.console across await boundaries in an async HTTP handler creates a textbook race condition: when two requests overlap, Request B captures Request A's patched console as its originalConsole, and A's finally block restores B's interceptor, permanently corrupting log routing for the lifetime of the process — 14+ unresolved comments on this exact pattern remain open.
  • The code parameter received from req.json() is executed directly via tseval with no sandboxing, allowing any caller who can reach this endpoint to execute arbitrary code in the server process — a critical security vulnerability flagged repeatedly in prior reviews and still unresolved.
  • Buffer.from(code) is used as a global in a file that exhibits Deno runtime characteristics (export default { fetch }, Deno stack trace parsing in parseError); Buffer is not a Deno global without explicit Node compatibility mode, meaning this will throw ReferenceError: Buffer is not defined in the intended deployment environment.
Files requiring special attention
  • packages/mcp-server/src/code-tool-worker.ts
  • packages/mcp-server/src/instructions.ts

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

0 participants